﻿#include "udpackserver.h"
#include "serverwritesession.h"
#include "serverreadsession.h"
#include "utils.h"

#include <QFile>

//#include <netinet/in.h>
#include <winsock.h>

namespace TFTP {

ServerWriteSession *UdpAckServer::findWSession(const TransferInfo &ti)
{
    for(QList<ServerWriteSession*>::iterator it = writes.begin(); it != writes.end(); it++)
    {
        TransferInfo tf = (*it)->transferInfo();
        if (tf == ti)
        {
            return (*it);
        }
    }
    return nullptr;
}

ServerReadSession *UdpAckServer::findRSession(const TransferInfo &ti)
{
    for(QList<ServerReadSession*>::iterator it = reads.begin(); it != reads.end(); it++)
    {
        TransferInfo th = (*it)->transferInfo();
        if ( th== ti )
        {
            return (*it);
        }
    }
    return nullptr;
}


UdpAckServer::UdpAckServer(const QHostAddress &addr, quint16  port)
    : QObject()
    , address(addr)
    , port(port)
{
    socket = new QUdpSocket();
    connect(socket, &QUdpSocket::readyRead, this, &UdpAckServer::dataReceived);
    socket->bind(addr, port);
}

UdpAckServer::~UdpAckServer()
{
    delete socket;
    for(QList<ServerWriteSession*>::iterator it = writes.begin(); it != writes.end(); it++)
    {    delete (*it);}
}

void UdpAckServer::dataReceived()
{
    QByteArray buffer;
    qint64 dataLen = socket->pendingDatagramSize();
    buffer.resize(static_cast<int>(dataLen));
    socket->readDatagram(buffer.data(), buffer.size());

    TransferInfo ti(socket, socket->peerAddress(), socket->peerPort());


    //	QByteArray dgram( sd.bytesAvailable() );
    //	sd.readBlock( dgram.data(), dgram.size() );

    switch( ntohs(wordOfArray(buffer)[0]) )
    {
    case RRQ: {
        ServerReadSession *rs = findRSession(ti);
        if ( rs )
        {
            ti.sendError(IllegalOp, "来自同一对等方的重复写入请求");
            return;
        }

        reads.push_back( new ServerReadSession(ti, buffer) );
    } break;
    case ACK: {
        ServerReadSession *rs = findRSession(ti);
        if ( !rs )
        {
            ti.sendError(IllegalOp, "无RRQ的ACK数据包");
            return;
        }

        if ( rs->parseAck(buffer) )
        {
            emit sentFile(rs->currentFile(), rs->currentFilename());
            reads.removeOne(rs);
            delete rs;
        }
    } break;
    case WRQ: {
        ServerWriteSession *ws = findWSession(ti);
        if ( ws )
        {
            qWarning("来自同一对方的重复写入请求");
            ti.sendError(IllegalOp, "来自同一对方的重复写入请求");
            return;
        }

        writes.push_back( new ServerWriteSession(ti, buffer) );
    } break;
    case DATA: {
        ServerWriteSession *ws = findWSession(ti);
        if ( !ws )
        {
            qWarning("无WRQ的数据包");
            ti.sendError(IllegalOp, "无WRQ的数据包");
            return;
        }

        if ( ws->parseData(buffer) )
        {
            emit receivedFile(ws->currentFile(), ws->currentFilename());
            writes.removeOne(ws);
            delete ws;
        }
    } break;
    case ERROR: {
        Session *s;
        if ( (s = findWSession(ti) ) )
        {
            writes.removeOne(reinterpret_cast<ServerWriteSession*>(s));
        }else if ( (s = findRSession(ti) ) )
        {
            reads.removeOne(reinterpret_cast<ServerReadSession*>(s));
        }else{
            qWarning("在没有为对等方打开会话的情况下收到错误");
        }

        if ( s )
            qWarning(
                        "收到错误数据包，对等会话中止\n%s [%d]",
                        buffer.data() + 4,
                        ntohs(wordOfArray(buffer)[1])
                    );
    } break;
    default:
        ti.sendError(IllegalOp, "非法TFTP操作码");
        return;
    }
}

};

